package org.ectar.papi
{
	import mx.collections.ArrayCollection;
	
	import org.ectar.papi.data.GAlbum;
	import org.ectar.papi.data.GAuthor;
	import org.ectar.papi.data.GComment;
	import org.ectar.papi.data.GEORss;
	import org.ectar.papi.data.GEntry;
	import org.ectar.papi.data.GExif;
	import org.ectar.papi.data.GMedia;
	import org.ectar.papi.data.GPhoto;
	import org.ectar.papi.data.GThumbnail;
	import org.ectar.papi.data.Link;
	
	/**
	 * 
	 * @author Mykhaylo Lytvynyuk
	 * 
	 * Class contains a number of methods which do necessary job to process
	 * Google Data Atom feeds into more sophisticated entiities such as Objects 
	 * of different type.
	 * 
	 * Typical usage is to give in parameter XML feed - receive as return populated object
	 * 
	 */
	internal class GDataHelper
	{
		// Define and use atom namespace
        private namespace atom = "http://www.w3.org/2005/Atom";
        use namespace atom;
        
        private namespace media = "http://search.yahoo.com/mrss/" ;
        use namespace media;
        
        private namespace gphoto = "http://schemas.google.com/photos/2007" ;
        use namespace gphoto;
        
		private namespace exif = "http://schemas.google.com/photos/exif/2007";
		use namespace exif;

		private namespace geo = "http://www.w3.org/2003/01/geo/wgs84_pos#";
		use namespace geo;
		
		private namespace gml = "http://www.opengis.net/gml";
		use namespace gml;
		
		private namespace georss = "http://www.georss.org/georss";
		use namespace georss;

		/**
		 * Parses XML feed of album entry and return populated object
		 *  
		 * @param xml - XML feed
		 * @return - populated instance of GAlbum object
		 * 
		 */
		internal static function parseAlbum(xml:XML):GAlbum {
			var album:GAlbum = new GAlbum();
			
			if(xml) {
				album.id = xml.id;
				//photo.category = xml.categoory; // @TODO - figure out what a heck is this
				album.title = xml.title;			
				album.published = xml.published;
				album.updated = xml.updated;
				album.summary = xml.summary;
				album.rights = xml.rights;
				album.title = xml.title;
				album.subtitle = xml.subtitle;
				
				/* Parsing links */
				var links:ArrayCollection = new ArrayCollection();
				
				// gphoto section
				album.gphoto = parseGphoto(xml);
				
				// media section
				album.icon =  xml.media::group.media::content.@url; // @TODO will be removed
				album.media = parseMedia(xml);
				
				for each (var item1:XML in xml.link) {
					var link:Link = new Link();
					
					link.href = item1.@href;
					link.rel = item1.@rel;
					link.type = item1.@type;
									
					links.addItem(link);
				}
				
				album.link = links;	// @TODO Figure out proper usage of this links	
				
				var itemX:XMLList = xml.entry;
				
				if(itemX.length() != 0) {
					var photos:ArrayCollection = new ArrayCollection();
					
					for each (var item:XML in xml.entry) {
						var photo:GEntry = parsePhoto(item);
						photos.addItem(photo);
					}
					
					album.photos = photos;				
				}
			}
			return album;
		}
		
		
		/**
		 * Parses XML feed of albums entries and return an Array of objects
		 *  
		 * @param xml - XML feed
		 * @return -an ArrayCollection of GAlbum instances
		 * 
		 */
		internal static function parseAlbums(xml:XML):ArrayCollection {
			
			var albums:ArrayCollection = new ArrayCollection();

			if(xml)
				for each (var item:XML in xml.entry) {
					var album:GAlbum = new GAlbum();
					album = parseAlbum(item);
					albums.addItem(album);
				}
			
			return albums;
		}
		
		
		/**
		 * Parses XML feed of photograph entry and return populated object
		 *  
		 * @param xml - XML feed
		 * @return - populated instance of GPhoto object
		 * 
		 */
		internal static function parsePhoto(xml:XML):GEntry {
			
			var photo:GEntry = new GEntry();
			
			if(xml) {
				// [0] because xml.id returns XMLList including also gphoto:id
				photo.id = xml.id[0];
				//photo.category = xml.categoory; // @TODO - figure out what a heck is this
				photo.title = xml.title;
				photo.subtitle = xml.subtitle;
				photo.published = xml.published;
				photo.updated = xml.updated;
				photo.summary = xml.summary;
				photo.content = xml.content;
				
				/* Parsing links */
				var links:ArrayCollection = new ArrayCollection();
				
				for each (var item1:XML in xml.link) {
					var link:Link = new Link();
					
					link.href = item1.@href;
					link.rel = item1.@rel;
					link.type = item1.@type;
									
					links.addItem(link);
				}
				
				photo.link = links;	// @TODO Figure out proper usage of this links	
				
				// gphoto section
				photo.gphoto = parseGphoto(xml);
				
				// media section
				photo.icon =  xml.media::group.media::content.@url; // @TODO will be removed
				photo.media = parseMedia(xml);
				
				// Exif section
				photo.exif = parseExif(xml.exif::tags[0]);
					
				photo.georss = parseGEO(xml);
				
				photo.author = parseAuthor(xml.author[0]);
			}
			return photo;
		}
		
		
		/**
		 * Parses XML feed of photographs entries and return populated object
		 * 
		 * @param xml - XML feed
		 * @return - an ArrayCollection of GPhoto instances
		 * 
		 */
		internal static function parsePhotos(xml:XML):ArrayCollection {
			var photos:ArrayCollection = new ArrayCollection();

			if(xml)
				for each (var item:XML in xml.entry) {
					var photo:GEntry = parsePhoto(item);				
					photos.addItem(photo);
				}
			
			return photos;
		}
		
		/**
		 *  Parses XML feed of photographs EXIF information and return populated object
		 *  
		 * @param xml - XML feed
		 * @return  - populated instance of GExif object
		 * 
		 */
		internal static function parseExif(xml:XML):GExif {
			var exifOb:GExif = new GExif();
			
			if(xml) {
				exifOb.exposure = xml.exif::exposure;
				exifOb.flash = xml.exif::flash;
				exifOb.focallength = xml.exif::focallength;
				exifOb.fstop = xml.exif::fstop;
				exifOb.imageUniqueID = xml.exif::imageUniqueID;
				exifOb.iso = xml.exif::iso;
				exifOb.make = xml.exif::make;
				exifOb.model = xml.exif::model;
				exifOb.time = xml.exif::time;
			}

			return exifOb;
		}
		
		private static function parseGphoto(xml:XML):GPhoto {
			// gphoto section
			var gph:GPhoto = new GPhoto();
			if(xml) {
				gph.id = xml.gphoto::id;
				gph.version = xml.gphoto::version;
				gph.albumid = xml.gphoto::albumid;
				gph.width = xml.gphoto::width;
				gph.height = xml.gphoto::height
				gph.client = xml.gphoto::client;
				gph.checksum = xml.gphoto::checksum;
				gph.timestamp = xml.gphoto::timestamp;
				gph.commentCount = xml.gphoto::commentCount;
				gph.commentingEnabled = xml.gphoto::commentingEnabled;	
				gph.name = xml.gphoto::name;
				gph.location = xml.gphoto::location;
				gph.access = xml.gphoto::access;
				gph.numphotos = xml.gphoto::numphotos;
				gph.numphotosremaining = xml.gphoto::numphotosremaining;
				gph.user = xml.gphoto::user;
				gph.nickname = xml.gphoto::nickname;
				gph.rotation = xml.gphoto::rotation;
				gph.position = xml.gphoto::position;
				gph.bytesUsed = xml.gphoto::bytesUsed;
				gph.photoid = xml.gphoto::photoid;
				gph.weight = xml.gphoto::weight;
				gph.crowded_length = xml.gphoto::crowded_length;
				
				if(xml.gphoto::viewCount && xml.gphoto::viewCount.length != 0)
					gph.viewCount = parseInt(xml.gphoto::viewCount);
				
				gph.license = xml.gphoto::license;
				gph.imageVersion = xml.gphoto::imageVersion;
			}
			return gph;
		}
		
		private static function parseMedia(xml:XML):GMedia {
			
			var mediaData:GMedia = new GMedia();
			
			if(xml) {
				mediaData.title =  xml.media::group.media::title;
				mediaData.description = xml.media::group.media::description;
				
				// Parsing keywords
				var keywords:ArrayCollection = new ArrayCollection();
				
				for each (var item2:XML in xml.media::group.media::keywords) {
					var keyword:String;
					
					keyword = item2;
									
					keywords.addItem(keyword);
				}
				mediaData.keywords = keywords;
								
				// Parsing thumbnails
				var thumbnails:ArrayCollection = new ArrayCollection();
				
				for each (var item3:XML in xml.media::group.media::thumbnail) {
					var thumbnail:GThumbnail = new GThumbnail()
					
					thumbnail.url = item3.@url;
					thumbnail.width = item3.@width;
					thumbnail.height = item3.@height;				
									
					thumbnails.addItem(thumbnail);
				}
				mediaData.thumbnail = thumbnails;
				
				
				mediaData.content.url = xml.media::group.media::content.@url;
				mediaData.content.height = xml.media::group.media::content.@height;
				mediaData.content.width = xml.media::group.media::content.@width;
				mediaData.content.type = xml.media::group.media::content.@type;
				mediaData.content.medium = xml.media::group.media::content.@medium;
																
				mediaData.credit = xml.media::group.media::credit;
			}
			return mediaData;
		}
		
		private static function parseGEO(xml:XML):GEORss {
			var geo:GEORss = new GEORss();
			if(xml) {
				geo.geoposition = xml.georss::where.gml::Point.gml::pos;
				var sep:Array = geo.geoposition.split(" ");
				geo.lat = sep[0];
				geo.long = sep[1];
			}
			return geo;
		}
		
		private static function parseAuthor(xml:XML):GAuthor {
			
			var author:GAuthor = new GAuthor();
			
			if(xml) {
				
				author.email = xml.email;
				author.uri = xml.uri;
				author.name = xml.name;
				
				author.gphoto = parseGphoto(xml);
			}
			
			return author;
		}
		
		internal static function parseComments(xml:XML):ArrayCollection {
			
			var comments:ArrayCollection = new ArrayCollection();
			
			if(xml)
				for each(var item:XML in xml.entry) {
				
					var comment:GComment = new GComment();
				
					if(item) {
						comment.author = parseAuthor(xml);				
						comment.category = item.category;
						comment.content = item.content;
						comment.gphoto = parseGphoto(item);
						comment.id = item.id;
						
						/* TODO make function for parsing LInks */
						/* Parsing links */
						var links:ArrayCollection = new ArrayCollection();
						
						for each (var item1:XML in item.link) {
							var link:Link = new Link();
							
							link.href = item1.@href;
							link.rel = item1.@rel;
							link.type = item1.@type;
											
							links.addItem(link);
						}
						
						comment.link = links;	// @TODO Figure out proper usage of this links
						
						comment.published = item.published
						comment.title = item.title
						comment.updated = item.updated
					}
				}
			
			return comments;
		}		
	}
}